package org.etnaframework.module.base.utils;

import com.fasterxml.jackson.core.type.TypeReference;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;

import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalTime;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Function;

/**
 * 增强版 Map<String, Object>
 * 用于json/jdbc等场景数据绑定(DataBind)
 * <p>
 * 注意：多线程不安全
 *
 * @author jasyaf
 * @since 2023-09-01
 */
public class DbMap implements Map<String, Object> {

    /**
     * 简单封装类型，模仿org.springframework.util.ClassUtils，但加入了额外内容
     */
    private static final Set<Type> primitiveWrapperTypes = new HashSet<>();

    static {
        // java基本类型
        primitiveWrapperTypes.add(boolean.class);
        primitiveWrapperTypes.add(Boolean.class);
        primitiveWrapperTypes.add(byte.class);
        primitiveWrapperTypes.add(Byte.class);
        primitiveWrapperTypes.add(char.class);
        primitiveWrapperTypes.add(Character.class);
        primitiveWrapperTypes.add(short.class);
        primitiveWrapperTypes.add(Short.class);
        primitiveWrapperTypes.add(int.class);
        primitiveWrapperTypes.add(Integer.class);
        primitiveWrapperTypes.add(long.class);
        primitiveWrapperTypes.add(Long.class);
        primitiveWrapperTypes.add(float.class);
        primitiveWrapperTypes.add(Float.class);
        primitiveWrapperTypes.add(double.class);
        primitiveWrapperTypes.add(Double.class);

        // 字符串
        primitiveWrapperTypes.add(String.class);

        // 大数值类型
        primitiveWrapperTypes.add(BigInteger.class);
        primitiveWrapperTypes.add(BigDecimal.class);

        // 二进制内容
        primitiveWrapperTypes.add(byte[].class);
        primitiveWrapperTypes.add(Byte[].class);

        // 时间日期
        primitiveWrapperTypes.add(java.util.Date.class);
        primitiveWrapperTypes.add(java.sql.Date.class);
        primitiveWrapperTypes.add(LocalDate.class);
        primitiveWrapperTypes.add(LocalTime.class);
    }

    /**
     * 判断当前Class是否是简单封装类型（包括String）
     */
    public static boolean isPrimitiveWrapperType(Type clazz) {
        return primitiveWrapperTypes.contains(clazz);
    }

    /**
     * 判断当前Class是否不是简单封装类型（包括String）
     */
    public static boolean isNotPrimitiveWrapperType(Type clazz) {
        return !isPrimitiveWrapperType(clazz);
    }

    protected Map<String, Object> inner;

    public DbMap() {
        inner = new LinkedHashMap<>();
    }

    public DbMap(int size) {
        inner = new LinkedHashMap<>(size);
    }

    @Override
    public int size() {
        return inner.size();
    }

    @Override
    public boolean isEmpty() {
        return inner.isEmpty();
    }

    @Override
    public boolean containsKey(Object key) {
        return inner.containsKey(key);
    }

    @Override
    public boolean containsValue(Object value) {
        return inner.containsValue(value);
    }

    @Override
    public Object get(Object key) {
        return inner.get(key);
    }

    /**
     * 添加键值对，如果key为null则不会被加入（注意允许value为null）
     */
    @Override
    public Object put(String key, Object value) {
        if (null == key) {
            return null;
        }
        return inner.put(key, value);
    }

    @Override
    public Object putIfAbsent(String key, Object value) {
        if (null == value) {
            return get(key);
        }
        return put(key, value);
    }

    @Override
    public Object compute(String key, BiFunction<? super String, ? super Object, ?> remappingFunction) {
        return inner.compute(key, remappingFunction);
    }

    @Override
    public Object computeIfAbsent(String key, Function<? super String, ?> mappingFunction) {
        return inner.computeIfAbsent(key, mappingFunction);
    }

    @Override
    public Object computeIfPresent(String key, BiFunction<? super String, ? super Object, ?> remappingFunction) {
        return inner.computeIfPresent(key, remappingFunction);
    }

    @Override
    public Object remove(Object key) {
        return inner.remove(key);
    }

    @Override
    public void putAll(Map<? extends String, ?> m) {
        for (Entry<? extends String, ?> e : m.entrySet()) {
            put(e.getKey(), e.getValue());
        }
    }

    @Override
    public void clear() {
        inner.clear();
    }

    @Override
    public Set<String> keySet() {
        return inner.keySet();
    }

    @Override
    public Collection<Object> values() {
        return inner.values();
    }

    @Override
    public Set<Entry<String, Object>> entrySet() {
        return inner.entrySet();
    }

    @Override
    public Object getOrDefault(Object key, Object defaultValue) {
        return inner.getOrDefault(key, defaultValue);
    }

    @Override
    public void forEach(BiConsumer<? super String, ? super Object> action) {
        inner.forEach(action);
    }

    @Override
    public void replaceAll(BiFunction<? super String, ? super Object, ?> function) {
        inner.replaceAll(function);
    }

    @Override
    public boolean remove(Object key, Object value) {
        return inner.remove(key, value);
    }

    @Override
    public boolean replace(String key, Object oldValue, Object newValue) {
        return inner.replace(key, oldValue, newValue);
    }

    @Override
    public Object replace(String key, Object value) {
        return inner.replace(key, value);
    }

    @Override
    public Object merge(String key, Object value, BiFunction<? super Object, ? super Object, ?> remappingFunction) {
        return inner.merge(key, value, remappingFunction);
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return new DbMap(inner);
    }

    @Override
    public int hashCode() {
        return inner.hashCode();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        DbMap dm = (DbMap) o;
        return inner.equals(dm.inner);
    }

    /**
     * 返回JSON格式字符串
     */
    @Override
    public String toString() {
        String json = JacksonUtils.toJson(inner);
        return null == json ? "{}" : json;
    }

    /**
     * 返回JSON格式字符串（对JSON进行了格式化）
     */
    public String toStringPretty() {
        String json = JacksonUtils.toJsonPretty(inner);
        return null == json ? "{}" : json;
    }

    /**
     * 转换为Java对象，转换失败返回null
     */
    @Nullable
    public <T> T toBean(Class<T> clazz) {
        return JacksonUtils.toBean(inner, clazz);
    }

    /**
     * 转换为Java对象，转换失败返回null
     */
    @Nullable
    public <T> T toBean(TypeReference<T> type) {
        return JacksonUtils.toBean(inner, type);
    }

    /**
     * 初始化Map，如果key为null则不会被加入（注意允许value为null）
     */
    public DbMap(Map<?, ?> map) {
        inner = new LinkedHashMap<>(map.size());
        for (Entry<?, ?> e : map.entrySet()) {
            if (null != e.getKey()) {
                put(String.valueOf(e.getKey()), e.getValue());
            }
        }
    }

    /**
     * 初始化Map，按key1,value1,key2,value2的顺序传入构造，如果key为null则不会被加入（注意允许value为null）
     */
    public DbMap(Object... keyValue) {
        inner = new LinkedHashMap<>(keyValue.length);
        if (keyValue.length % 2 != 0) {
            throw new IllegalArgumentException("keyValue.length is invalid: " + keyValue.length + " (must be an even number)");
        }
        for (int i = 0; i < keyValue.length; ) {
            Object key = keyValue[i++];
            Object value = keyValue[i++];
            if (null != key) {
                put(String.valueOf(key), value);
            }
        }
    }

    /**
     * 构造器方式添加键值对，如果key为null则不会被加入（注意允许value为null）
     */
    public DbMap append(String key, Object value) {
        put(key, value);
        return this;
    }

    /**
     * 构造器方式添加键值对，如果value已存在则不会被加入，如果key为null则不会被加入（注意允许value为null）
     */
    public DbMap appendIfAbsent(String key, Object value) {
        if (null != value) {
            put(key, value);
        }
        return this;
    }

    /**
     * 构造器方式添加键值对，如果key为null则不会被加入（注意允许value为null）
     */
    public DbMap append(Map<? extends String, ?> data) {
        putAll(data);
        return this;
    }

    public <T> T get(String key, Class<T> clazz) {
        if (isPrimitiveWrapperType(clazz)) {
            throw new IllegalArgumentException("PrimitiveWrapperType " + clazz.getName() + ", use getXXX methods instead");
        }
        Object value = get(key);
        if (null == value) {
            return null;
        }
        if (clazz == value.getClass() || clazz.isAssignableFrom(value.getClass())) {
            return clazz.cast(value);
        }
        if (value instanceof Map) {
            return JacksonUtils.toBean((Map<?, ?>) value, clazz);
        }
        return JacksonUtils.toBean(JacksonUtils.toJson(value), clazz);
    }

    public <T> T get(String key, TypeReference<T> type) {
        if (isPrimitiveWrapperType(type.getType())) {
            throw new IllegalArgumentException("PrimitiveWrapperType " + type.getType().getTypeName() + ", use getXXX methods instead");
        }
        Object value = get(key);
        if (null == value) {
            return null;
        }
        if (value instanceof Map) {
            return JacksonUtils.toBean((Map<?, ?>) value, type);
        }
        return JacksonUtils.toBean(JacksonUtils.toJson(value), type);
    }

    public <T> List<T> getList(String key, Class<T> clazz) {
        Object value = get(key);
        if (null == value) {
            return null;
        }
        List<T> result;
        if (value instanceof CharSequence) {
            result = JacksonUtils.toList(value.toString(), clazz);
        } else {
            result = JacksonUtils.toList(JacksonUtils.toJson(value), clazz);
        }
        return result;
    }

    /**
     * 获取指定key对应的值，会被转换为{@link DbMap}
     * 如果对返回的内容做了改动，会影响到当前map
     * <p>
     * 本接口不会返回null，支持链式调用
     */
    @NonNull
    public DbMap getMap(String key) {
        Object value = get(key);
        if (null == value) {
            DbMap v = new DbMap();
            put(key, v);
            return v;
        }
        if (value instanceof DbMap) {
            return (DbMap) value;
        }
        if (value instanceof Map) {
            DbMap v = new DbMap((Map<?, ?>) value);
            put(key, v);
            return v;
        }
        if (value instanceof String) {
            DbMap v = JacksonUtils.toMap((String) value);
            put(key, v);
            return v;
        }
        DbMap v = JacksonUtils.toMap(JacksonUtils.toJson(value));
        put(key, v);
        return v;
    }

    /**
     * 获取指定key对应的值，会被转换为{@link DbMap}列表
     * 如果对返回的内容做了改动，会影响到当前map
     * <p>
     * 本接口不会返回null，支持链式调用
     */
    @NonNull
    public List<DbMap> getList(String key) {
        Object value = get(key);
        if (null == value) {
            List<DbMap> v = new ArrayList<>();
            put(key, v);
            return v;
        }
        if (value instanceof Collection) {
            Collection<?> list = (Collection<?>) value;
            List<DbMap> result = new ArrayList<>(list.size());
            for (Object o : list) {
                if (o instanceof DbMap) {
                    result.add((DbMap) o);
                } else if (o instanceof Map) {
                    result.add(new DbMap((Map<?, ?>) o));
                } else {
                    result.add(JacksonUtils.toMap(o.toString()));
                }
            }
            put(key, result);
            return result;
        }
        List<DbMap> v = new ArrayList<>();
        put(key, v);
        return v;
    }

    public String getString(String key, String defaultValue) {
        Object value = get(key);
        return null == value ? defaultValue : value.toString();
    }

    public byte[] getBytes(String key, byte[] defaultValue) {
        Object value = get(key);
        if (value instanceof byte[]) {
            return (byte[]) value;
        }
        return defaultValue;
    }

    public Byte getByte(String key, Byte defaultValue) {
        return toByte(get(key), defaultValue);
    }

    public Boolean getBool(String key, Boolean defaultValue) {
        return toBool(get(key), defaultValue);
    }

    public Character getChar(String key, Character defaultValue) {
        return toChar(get(key), defaultValue);
    }

    /**
     * 转换为Short，注意不能处理小数，会导致返回defaultValue
     */
    public Short getShort(String key, Short defaultValue) {
        return toShort(get(key), defaultValue);
    }

    /**
     * 转换为Integer，注意不能处理小数，会导致返回defaultValue
     */
    public Integer getInt(String key, Integer defaultValue) {
        return toInt(get(key), defaultValue);
    }

    /**
     * 转换为Long，注意不能处理小数，会导致返回defaultValue
     */
    public Long getLong(String key, Long defaultValue) {
        return toLong(get(key), defaultValue);
    }

    public Float getFloat(String key, Float defaultValue) {
        return toFloat(get(key), defaultValue);
    }

    public Double getDouble(String key, Double defaultValue) {
        return toDouble(get(key), defaultValue);
    }

    public BigInteger getBigInteger(String key, BigInteger defaultValue) {
        return toBigInteger(get(key), defaultValue);
    }

    public BigDecimal getBigDecimal(String key, BigDecimal defaultValue) {
        return toBigDecimal(get(key), defaultValue);
    }

    public BigDecimal getBigDecimal(String key, int newScale, RoundingMode roundingMode, BigDecimal defaultValue) {
        return toBigDecimal(get(key), newScale, roundingMode, defaultValue);
    }

    /**
     * 根据枚举名称转换成枚举类型，如果转换失败返回defaultValue
     */
    public <T extends Enum<?>> T getEnumByName(String key, Class<T> enumClass, T defaultValue) {
        return toEnumByName(enumClass, get(key), defaultValue);
    }

    /**
     * 根据枚举序号转换成枚举类型，如果转换失败返回defaultValue
     */
    public <T extends Enum<?>> T getEnumByOrdinal(String key, Class<T> enumClass, T defaultValue) {
        Integer ordinal = getInt(key, null);
        if (null == ordinal) {
            return defaultValue;
        }
        return toEnumByOrdinal(enumClass, ordinal, defaultValue);
    }

    /**
     * 根据枚举的code值转换成枚举类型，如果转换失败返回defaultValue
     * 这里需要枚举类型实现{@link EnumWithCode}，注意code不允许重复，如果重复了会报错
     */
    public <T extends EnumWithCode<?>> T getEnumByCode(String key, Class<T> enumClass, T defaultValue) {
        return toEnumByCode(enumClass, getString(key, null), defaultValue);
    }

    public Date getDate(String key, String dateFormat, Date defaultValue) {
        Date date = DatetimeUtils.parse(getString(key, null), dateFormat);
        return null == date ? defaultValue : date;
    }

    public Date getDate(String key, String dateFormat, TimeZone timeZone, Date defaultValue) {
        Date date = DatetimeUtils.parse(getString(key, null), dateFormat, timeZone);
        return null == date ? defaultValue : date;
    }

    /**
     * 将指定key对应的字符串转换为{@link Date}，持智能判断时间格式，提高兼容性，使用当前系统默认的时区，如果转换失败返回defaultValue
     */
    public Date getDateSmartly(String key, Date defaultValue) {
        Date date = DatetimeUtils.parseSmartly(getString(key, null));
        return null == date ? defaultValue : date;
    }

    /**
     * 将指定key对应的字符串转换为{@link Date}，持智能判断时间格式，提高兼容性，使用指定的时区，如果转换失败返回defaultValue
     */
    public Date getDateSmartly(String key, TimeZone timeZone, Date defaultValue) {
        Date date = DatetimeUtils.parseSmartly(getString(key, null), timeZone);
        return null == date ? defaultValue : date;
    }

    /**
     * 转换为Byte，如果转换失败返回defaultValue
     */
    public static Byte toByte(Object value, Byte defaultValue) {
        if (null == value) {
            return defaultValue;
        }
        try {
            return Byte.valueOf(value.toString());
        } catch (NumberFormatException e) {
            return defaultValue;
        }
    }

    /**
     * 转换为Boolean，如果转换失败返回defaultValue
     *
     * @return 字符串为true/yes/y/1/是 时都返回true
     */
    public static Boolean toBool(Object value, Boolean defaultValue) {
        if (null == value) {
            return defaultValue;
        }
        String val = value.toString();
        return val.equals("true") || val.equalsIgnoreCase("yes") || val.equalsIgnoreCase("y") || val.equals("1") || val.equals("是");
    }

    /**
     * 转换为Character，默认取字符串的第1个字符，如果转换失败返回defaultValue
     */
    public static Character toChar(Object value, Character defaultValue) {
        if (null == value) {
            return defaultValue;
        }
        String val = value.toString();
        if (val.isEmpty()) {
            return defaultValue;
        }
        return val.charAt(0);
    }

    /**
     * 转换为Short，注意不能处理小数，会导致返回defaultValue
     */
    public static Short toShort(Object value, Short defaultValue) {
        if (null == value) {
            return defaultValue;
        }
        try {
            return Short.valueOf(value.toString());
        } catch (NumberFormatException e) {
            return defaultValue;
        }
    }

    /**
     * 转换为Integer，注意不能处理小数，会导致返回defaultValue
     */
    public static Integer toInt(Object value, Integer defaultValue) {
        if (null == value) {
            return defaultValue;
        }
        try {
            return Integer.valueOf(value.toString());
        } catch (NumberFormatException e) {
            return defaultValue;
        }
    }

    /**
     * 转换为Long，注意不能处理小数，会导致返回defaultValue
     */
    public static Long toLong(Object value, Long defaultValue) {
        if (null == value) {
            return defaultValue;
        }
        try {
            return Long.valueOf(value.toString());
        } catch (NumberFormatException e) {
            return defaultValue;
        }
    }

    /**
     * 转换为Float，如果转换失败返回defaultValue
     */
    public static Float toFloat(Object value, Float defaultValue) {
        if (null == value) {
            return defaultValue;
        }
        try {
            return Float.valueOf(value.toString());
        } catch (NumberFormatException e) {
            return defaultValue;
        }
    }

    /**
     * 字符串转换为Double，如果转换失败返回defaultValue
     */
    public static Double toDouble(Object value, Double defaultValue) {
        if (null == value) {
            return defaultValue;
        }
        try {
            return Double.valueOf(value.toString());
        } catch (NumberFormatException e) {
            return defaultValue;
        }
    }

    public static BigInteger toBigInteger(Object value, BigInteger defaultValue) {
        if (null == value) {
            return defaultValue;
        }
        try {
            return new BigInteger(value.toString());
        } catch (NumberFormatException e) {
            return defaultValue;
        }
    }

    public static BigDecimal toBigDecimal(Object value, BigDecimal defaultValue) {
        if (null == value) {
            return defaultValue;
        }
        try {
            return new BigDecimal(value.toString());
        } catch (NumberFormatException e) {
            return defaultValue;
        }
    }

    public static BigDecimal toBigDecimal(Object value, int newScale, RoundingMode roundingMode, BigDecimal defaultValue) {
        if (null == value) {
            return defaultValue;
        }
        try {
            return new BigDecimal(value.toString()).setScale(newScale, roundingMode);
        } catch (NumberFormatException e) {
            return defaultValue.setScale(newScale, roundingMode);
        }
    }

    /**
     * 根据枚举名称转换成枚举类型，如果转换失败返回defaultValue
     */
    @SuppressWarnings("unchecked")
    public static <T extends Enum<?>> T toEnumByName(Class<T> enumClass, Object name, T defaultValue) {
        if (null == name) {
            return defaultValue;
        }
        try {
            return (T) Enum.valueOf(enumClass.asSubclass(Enum.class), String.valueOf(name));
        } catch (Throwable e) {
            return defaultValue;
        }
    }

    /**
     * 根据枚举序号转换成枚举类型，如果转换失败返回defaultValue
     */
    public static <T extends Enum<?>> T toEnumByOrdinal(Class<T> enumClass, int ordinal, T defaultValue) {
        try {
            T[] enumConstants = enumClass.getEnumConstants();
            if (ordinal >= 0 && ordinal < enumConstants.length) {
                return enumConstants[ordinal];
            }
            return defaultValue;
        } catch (Throwable e) {
            return defaultValue;
        }
    }

    private static final Map<Class<? extends EnumWithCode<?>>, Map<String, EnumWithCode<?>>> enumWithCodeMaps = new LinkedHashMap<>();

    /**
     * 根据枚举的code值转换成枚举类型，如果转换失败返回defaultValue
     * 这里需要枚举类型实现{@link EnumWithCode}，注意code不允许重复，如果重复了会报错
     */
    @SuppressWarnings("unchecked")
    public static <T extends EnumWithCode<?>> T toEnumByCode(Class<T> enumClass, String codeString, T defaultValue) {
        if (null == codeString) {
            return defaultValue;
        }
        Map<String, EnumWithCode<?>> map = enumWithCodeMaps.get(enumClass);
        if (null == map) {
            synchronized (DbMap.class) {
                map = enumWithCodeMaps.get(enumClass);
                if (null == map) {
                    map = new LinkedHashMap<>();
                    for (T e : enumClass.getEnumConstants()) {
                        String code = e.getCode() != null ? e.getCode().toString() : null;
                        if (null == code) {
                            throw new IllegalArgumentException("enum " + enumClass.getName() + ".getCode() cannot return null");
                        }
                        if (map.containsKey(code)) {
                            throw new IllegalArgumentException("enum " + enumClass.getName() + " has duplicated .getCode()=" + code);
                        }
                        map.put(code, e);
                    }
                    enumWithCodeMaps.put(enumClass, map);
                }
            }
        }
        EnumWithCode<?> enumWithCode = map.get(codeString);
        if (null == enumWithCode) {
            return defaultValue;
        }
        return (T) enumWithCode;
    }

    private static final int truncateBaseLength = "...()...".length();

    /**
     * 将字符串简化处理，即当处理后的字符串大于指定长度时，处理为 头部...(总长度)...尾部 这样的字符串
     *
     * @param limit 字符串最大长度，<=0表示无限制，要求至少>10否则会返回满足格式最小长度的字符串（长度会超过传入的limit）
     */
    public static String truncate(String source, int limit) {
        if (limit <= 0 || null == source || source.isEmpty() || source.length() <= limit) {
            return source;
        }
        // ...()...要占8个字符，加上十进制的source长度，再加上截取后首尾各1个字符，即为limit的最小值
        int sourceStringLength = String.valueOf(source.length()).length();
        int minLimit = truncateBaseLength + sourceStringLength + 2;
        int actualLimit = Math.max(minLimit, limit);
        // 假定前后各保留x1和x2字符，可列出方程式 x1+x2+len(source)+8=actualLimit
        // 即 x1+x2=(actualLimit-8-len(source))
        int x = (actualLimit - truncateBaseLength - sourceStringLength);
        int x2 = x / 2;
        int x1 = x - x2;
        return source.substring(0, x1) + "...(" + source.length() + ")..." + source.substring(source.length() - x2);
    }

    private static String _escape(CharSequence source, Map<Character, String> map) {
        if (null == source) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < source.length(); i++) {
            char ch = source.charAt(i);
            if (ch == '\r') {
                continue;
            }
            String escaped = map.get(ch);
            if (escaped != null) {
                sb.append(escaped);
            } else {
                sb.append(ch);
            }
        }
        return sb.toString();
    }

    private static final Map<Character, String> LINE_BREAK_ESCAPE_MAP = new HashMap<>();

    static {
        LINE_BREAK_ESCAPE_MAP.put('\\', "\\\\");
        LINE_BREAK_ESCAPE_MAP.put('\r', "\\r");
        LINE_BREAK_ESCAPE_MAP.put('\n', "\\n");
        LINE_BREAK_ESCAPE_MAP.put('\'', "\\'");
    }

    /**
     * 转义文本中的换行符，后续在''之间使用
     */
    @NonNull
    public static String escapeLineBreak(CharSequence source) {
        return _escape(source, LINE_BREAK_ESCAPE_MAP);
    }

    private static final Map<Character, String> MARKDOWN_ESCAPE_MAP = new HashMap<>();

    static {
        MARKDOWN_ESCAPE_MAP.put('\r', "");
        MARKDOWN_ESCAPE_MAP.put('\n', "  \n");
        MARKDOWN_ESCAPE_MAP.put('\\', "\\\\");
        MARKDOWN_ESCAPE_MAP.put('`', "\\`");
        MARKDOWN_ESCAPE_MAP.put('*', "\\*");
        MARKDOWN_ESCAPE_MAP.put('{', "\\{");
        MARKDOWN_ESCAPE_MAP.put('}', "\\}");
        MARKDOWN_ESCAPE_MAP.put('[', "\\[");
        MARKDOWN_ESCAPE_MAP.put(']', "\\]");
        MARKDOWN_ESCAPE_MAP.put('(', "\\(");
        MARKDOWN_ESCAPE_MAP.put(')', "\\)");
        MARKDOWN_ESCAPE_MAP.put('#', "\\#");
        MARKDOWN_ESCAPE_MAP.put('+', "\\+");
        MARKDOWN_ESCAPE_MAP.put('!', "\\!");
        MARKDOWN_ESCAPE_MAP.put('-', "\\-");
        MARKDOWN_ESCAPE_MAP.put('=', "\\=");
        MARKDOWN_ESCAPE_MAP.put('<', "&lt;");
        MARKDOWN_ESCAPE_MAP.put('>', "&gt;");
        MARKDOWN_ESCAPE_MAP.put('&', "&amp;");
        MARKDOWN_ESCAPE_MAP.put('\u2002', " "); // Web提交的空格
    }

    /**
     * 转义文本中的markdown字符
     */
    @NonNull
    public static String escapeMarkdown(CharSequence source) {
        return _escape(source, MARKDOWN_ESCAPE_MAP);
    }
}
